#pragma once
#include "DXAMLCommon.h"
#include "CXcpList.h"


class CUIElement;
class VisualTree;
class LayoutTransitionStorage;


class CLayoutManager
{

public: 
	CLayoutManager(struct ICoreServices * pCoreServices, VisualTree * pVisualTree);
	~CLayoutManager();
	HRESULT UpdateLayout();
	HRESULT UpdateLayout(XUINT32 controlWidth, XUINT32 controlHeight);
	CUIElement * GetCurrentElement();
	void SetCurrentElement(CUIElement * pElement);
	CUIElement * GetTransitioningElement();
	void SetTransitioningElement(CUIElement * pElement);
	XBOOL GetRequiresMeasure();
	HRESULT EnterMeasure(CUIElement * pElement);
	HRESULT ExitMeasure(CUIElement * pElement);
	HRESULT EnterArrange(CUIElement * pElement);
	HRESULT ExitArrange(CUIElement * pElement);
	HRESULT SetLastExceptionElement(CUIElement * pLastExceptionElement);
	CUIElement * GetLastExceptionElement();
	void SetWantsLayoutUpdated(XUINT32 value);
	HRESULT EnqueueForSizeChanged(CUIElement * pElement, struct XSIZEF & oldSize);
	XUINT32 GetPreviousPluginWidth();
	XUINT32 GetPreviousPluginHeight();
	XBOOL GetUIAClientsListeningToProperty();
	XBOOL GetUIAClientsListeningToStructure();
	XBOOL DidErrorOccurDuringLayout();
	void ClearErrorOccurredDuringLayout();
	XBOOL GetIsInLayoutTransitionPhase();
	XBOOL GetIsInLayoutRealizationPhase();
	HRESULT RealizeRegisteredLayoutTransitions();
	HRESULT TransitionLayout();
	XUINT16 GetLayoutCounter();
	XUINT16 GetNextLayoutCounter();
	void IncrementLayoutCounter();
	XBOOL GetAllowTransitionsToRunUnderCurrentSubtree();
	void SetAllowTransitionsToRunUnderCurrentSubtree(XBOOL bAllow);
	static const XUINT32 MaxLayoutDepth;
	static const XUINT32 MaxLayoutIterations;
private: 
	HRESULT RaiseSizeChangedEvents();
	HRESULT RegisterElementForDeferrredTransition(CUIElement * pTarget, LayoutTransitionStorage * pStorage);
	HRESULT UnregisterElementForDeferredTransition(CUIElement * pTarget, LayoutTransitionStorage * pStorage);
	struct ICoreServices * m_pCoreServices;
	VisualTree * m_pVisualTree;
	CUIElement * m_pCurrentElement;
	CUIElement * m_pTransitioningElement;
	CUIElement * m_pLastExceptionElement;
	XINT32 m_cArrangesOnStack;
	XINT32 m_cMeasuresOnStack;
	XBOOL m_firePostLayoutEvents;
	XUINT32 m_previousPluginWidth;
	XUINT32 m_previousPluginHeight;
	XBOOL m_isInUpdateLayout;
	XBOOL m_isInTransitionRealization;
	struct XRECTF_WH m_arrangeRect;

	XBOOL m_fWantsLayoutUpdated;
	XBOOL m_bManagedPeerReferenceToLastExceptionElementTaken;

	XUINT16 m_layoutCounter:16;
public:
	struct SizeChangedQueueItem
	{
	public: 
		SizeChangedQueueItem(CUIElement * pElement, struct XSIZEF oldSize);
		~SizeChangedQueueItem();
		CUIElement * m_pElement;
		struct XSIZEF m_oldSize;

	};
private:
	CXcpList<SizeChangedQueueItem> m_sizeChangedQueue;


	XBOOL m_bUIAClientsListeningToProperty;
	XBOOL m_bUIAClientsListeningToStructure;
	XBOOL m_errorOcurredDuringLayout;
	XBOOL m_allowTransitionsToRun;
	XBOOL m_isInLayoutTransitionPhase;
	xvector<CUIElement *> m_deferredTransitions;
};

